mirror of
https://gitee.com/dotnetchina/MiniExcel.git
synced 2024-12-01 19:37:37 +08:00
[Bug] SaveAs file error (Excel cell max length 32,767 characters) #327
This commit is contained in:
parent
5db234d019
commit
f2f5e6d497
@ -487,11 +487,11 @@ MiniExcel.SaveAs(path, value);
|
||||
|
||||
|
||||
|
||||
#### 11. File Export
|
||||
#### 11. Byte Array File Export
|
||||
|
||||
Since 0.21.0, when value type is `byte[]` then system will save base64 string at cell by default, and when import system can be converted to `byte[]`. And if you don't want to use it, you can set `OpenXmlConfiguration.ConvertByteArrayToBase64String` to `false`, it can improve the system efficiency.
|
||||
Since 1.22.0, when value type is `byte[]` then system will save file path at cell by default, and when import system can be converted to `byte[]`. And if you don't want to use it, you can set `OpenXmlConfiguration.ConvertByteArrayToBase64String` to `false`, it can improve the system efficiency.
|
||||
|
||||
![image](https://user-images.githubusercontent.com/12729184/150499973-682be39a-8a98-4681-915f-45c8e8e725fb.png)
|
||||
![image](https://user-images.githubusercontent.com/12729184/153702334-c3b834f4-6ae4-4ddf-bd4e-e5005d5d8c6a.png)
|
||||
|
||||
|
||||
|
||||
|
@ -493,11 +493,11 @@ MiniExcel.SaveAs(path, value);
|
||||
|
||||
|
||||
|
||||
#### 11. 文件导出
|
||||
#### 11. Byte Array 文件导出
|
||||
|
||||
从 0.21.0 开始,当值类型为 `byte[]` 系统预设会转成 base64 字串以便导入时转回 `byte[]`,如不想转换可以将 `OpenXmlConfiguration.ConvertByteArrayToBase64String` 改为 `false`,能提升系统效率。
|
||||
从 1.22.0 开始,当值类型为 `byte[]` 系统预设会转成保存文件路径以便导入时转回 `byte[]`,如不想转换可以将 `OpenXmlConfiguration.ConvertByteArrayToBase64String` 改为 `false`,能提升系统效率。
|
||||
|
||||
![image](https://user-images.githubusercontent.com/12729184/150499973-682be39a-8a98-4681-915f-45c8e8e725fb.png)
|
||||
![image](https://user-images.githubusercontent.com/12729184/153702334-c3b834f4-6ae4-4ddf-bd4e-e5005d5d8c6a.png)
|
||||
|
||||
|
||||
|
||||
|
@ -496,11 +496,11 @@ MiniExcel.SaveAs(path, value);
|
||||
|
||||
|
||||
|
||||
#### 11. 文件導出
|
||||
#### 11. Byte Array 文件導出
|
||||
|
||||
從 0.21.0 開始,當值類型為 `byte[]` 系統預設會轉成 base64 字串以便導入時轉回 `byte[]`,如不想轉換可以將 `OpenXmlConfiguration.ConvertByteArrayToBase64String` 改為 `false`,能提升系統效率。
|
||||
從 1.22.0 開始,當值類型為 `byte[]` 系統預設會轉成保存文件路徑以便導入時轉回 `byte[]`,如不想轉換可以將 `OpenXmlConfiguration.ConvertByteArrayToBase64String` 改為 `false`,能提升系統效率。
|
||||
|
||||
![image](https://user-images.githubusercontent.com/12729184/150499973-682be39a-8a98-4681-915f-45c8e8e725fb.png)
|
||||
![image](https://user-images.githubusercontent.com/12729184/153702334-c3b834f4-6ae4-4ddf-bd4e-e5005d5d8c6a.png)
|
||||
|
||||
|
||||
|
||||
|
BIN
samples/images/TestIssue327.png
Normal file
BIN
samples/images/TestIssue327.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 55 KiB |
1
samples/other/TestIssue327.html
Normal file
1
samples/other/TestIssue327.html
Normal file
@ -0,0 +1 @@
|
||||
<html>Hello MiniExcel</html>
|
1
samples/other/TestIssue327.txt
Normal file
1
samples/other/TestIssue327.txt
Normal file
@ -0,0 +1 @@
|
||||
Hello MiniExcel
|
@ -668,10 +668,22 @@ namespace MiniExcelLibs.OpenXml
|
||||
{
|
||||
//TODO:optimize startswith
|
||||
//if str start with "data:image/png;base64," then convert to byte[] https://github.com/shps951023/MiniExcel/issues/318
|
||||
if (v != null && v.StartsWith("data:image/png;base64,"))
|
||||
value = Convert.FromBase64String(v.Substring(22));
|
||||
if (v != null && v.StartsWith("@@@fileid@@@,"))
|
||||
{
|
||||
var path = v.Substring(13);
|
||||
var stream = _archive.GetEntry(path).Open();
|
||||
byte[] bytes;
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
stream.CopyTo(ms);
|
||||
bytes = ms.ToArray();
|
||||
}
|
||||
value = bytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = v;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -14,15 +14,16 @@ using static MiniExcelLibs.Utils.ImageHelper;
|
||||
|
||||
namespace MiniExcelLibs.OpenXml
|
||||
{
|
||||
internal class ImageDto
|
||||
internal class FileDto
|
||||
{
|
||||
public string ID { get; set; } = $"R{Guid.NewGuid():N}";
|
||||
public string Extension { get; set; }
|
||||
public string Path { get { return $"xl/media/image{ID}.{Extension}"; } }
|
||||
public string Path2 { get { return $"/xl/media/image{ID}.{Extension}"; } }
|
||||
public string Path { get { return $"xl/media/{ID}.{Extension}"; } }
|
||||
public string Path2 { get { return $"/xl/media/{ID}.{Extension}"; } }
|
||||
public Byte[] Byte { get; set; }
|
||||
public int RowIndex { get; set; }
|
||||
public int CellIndex { get; set; }
|
||||
public bool IsImage { get; set; } = false;
|
||||
}
|
||||
internal class SheetDto
|
||||
{
|
||||
@ -44,7 +45,7 @@ namespace MiniExcelLibs.OpenXml
|
||||
private readonly bool _printHeader;
|
||||
private readonly object _value;
|
||||
private readonly List<SheetDto> _sheets = new List<SheetDto>();
|
||||
private readonly List<ImageDto> _images = new List<ImageDto>();
|
||||
private readonly List<FileDto> _files = new List<FileDto>();
|
||||
public ExcelOpenXmlSheetWriter(Stream stream, object value, string sheetName, IConfiguration configuration, bool printHeader)
|
||||
{
|
||||
this._stream = stream;
|
||||
@ -412,24 +413,31 @@ namespace MiniExcelLibs.OpenXml
|
||||
{
|
||||
// TODO: Setting configuration because it might have high cost?
|
||||
var format = ImageHelper.GetImageFormat(bytes);
|
||||
//it can't insert to zip first to avoid cache image to memory
|
||||
//because sheet xml is opening.. https://github.com/shps951023/MiniExcel/issues/304#issuecomment-1017031691
|
||||
//int rowIndex, int cellIndex
|
||||
var file = new FileDto()
|
||||
{
|
||||
Byte = bytes,
|
||||
RowIndex = rowIndex,
|
||||
CellIndex = cellIndex
|
||||
};
|
||||
if (format != ImageFormat.unknown)
|
||||
{
|
||||
//it can't insert to zip first to avoid cache image to memory
|
||||
//because sheet xml is opening.. https://github.com/shps951023/MiniExcel/issues/304#issuecomment-1017031691
|
||||
//int rowIndex, int cellIndex
|
||||
_images.Add(new ImageDto()
|
||||
{
|
||||
Extension = format.ToString(),
|
||||
Byte = bytes,
|
||||
RowIndex = rowIndex,
|
||||
CellIndex = cellIndex
|
||||
});
|
||||
file.Extension = format.ToString();
|
||||
file.IsImage = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
file.Extension = ".bin";
|
||||
}
|
||||
_files.Add(file);
|
||||
|
||||
//TODO:Convert to base64
|
||||
var base64 = $"@@@fileid@@@,{file.Path}";
|
||||
v = ExcelOpenXmlUtils.EncodeXML(base64);
|
||||
s = "4";
|
||||
}
|
||||
//TODO:Convert to base64
|
||||
var base64 = $"data:image/png;base64,{System.Convert.ToBase64String(bytes)}";
|
||||
v = ExcelOpenXmlUtils.EncodeXML(base64);
|
||||
s = "4";
|
||||
}
|
||||
else if (type == typeof(DateTime))
|
||||
{
|
||||
@ -570,9 +578,9 @@ namespace MiniExcelLibs.OpenXml
|
||||
|
||||
private void GenerateEndXml()
|
||||
{
|
||||
//Images
|
||||
//Files
|
||||
{
|
||||
foreach (var item in _images)
|
||||
foreach (var item in _files)
|
||||
{
|
||||
this.CreateZipEntry(item.Path, item.Byte);
|
||||
}
|
||||
@ -596,7 +604,7 @@ namespace MiniExcelLibs.OpenXml
|
||||
// drawing rel
|
||||
{
|
||||
var drawing = new StringBuilder();
|
||||
foreach (var i in _images)
|
||||
foreach (var i in _files.Where(w=>w.IsImage))
|
||||
{
|
||||
drawing.AppendLine($@"<Relationship Type=""http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"" Target=""{i.Path2}"" Id=""{i.ID}"" />");
|
||||
}
|
||||
@ -607,7 +615,7 @@ namespace MiniExcelLibs.OpenXml
|
||||
// drawing
|
||||
{
|
||||
var drawing = new StringBuilder();
|
||||
foreach (var i in _images)
|
||||
foreach (var i in _files.Where(w => w.IsImage))
|
||||
{
|
||||
drawing.Append($@"<xdr:oneCellAnchor>
|
||||
<xdr:from>
|
||||
@ -619,7 +627,7 @@ namespace MiniExcelLibs.OpenXml
|
||||
<xdr:ext cx=""609600"" cy=""190500"" />
|
||||
<xdr:pic>
|
||||
<xdr:nvPicPr>
|
||||
<xdr:cNvPr id=""{_images.IndexOf(i) + 1}"" descr="""" name=""2a3f9147-58ea-4a79-87da-7d6114c4877b"" />
|
||||
<xdr:cNvPr id=""{_files.IndexOf(i) + 1}"" descr="""" name=""2a3f9147-58ea-4a79-87da-7d6114c4877b"" />
|
||||
<xdr:cNvPicPr>
|
||||
<a:picLocks noChangeAspect=""1"" />
|
||||
</xdr:cNvPicPr>
|
||||
@ -645,7 +653,6 @@ namespace MiniExcelLibs.OpenXml
|
||||
}
|
||||
CreateZipEntry($"xl/drawings/drawing1.xml", "application/vnd.openxmlformats-officedocument.drawing+xml",
|
||||
_defaultDrawing.Replace("{{format}}", drawing.ToString()));
|
||||
|
||||
}
|
||||
|
||||
// workbook.xml 、 workbookRelsXml
|
||||
@ -674,7 +681,7 @@ namespace MiniExcelLibs.OpenXml
|
||||
|
||||
//[Content_Types].xml
|
||||
{
|
||||
var sb = new StringBuilder(@"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""yes""?><Types xmlns=""http://schemas.openxmlformats.org/package/2006/content-types""><Default ContentType=""application/xml"" Extension=""xml""/><Default ContentType=""image/jpeg"" Extension=""jpg""/><Default ContentType=""image/png"" Extension=""png""/><Default ContentType=""image/gif"" Extension=""gif""/><Default ContentType=""application/vnd.openxmlformats-package.relationships+xml"" Extension=""rels""/>");
|
||||
var sb = new StringBuilder(@"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""yes""?><Types xmlns=""http://schemas.openxmlformats.org/package/2006/content-types""><Default ContentType=""application/vnd.openxmlformats-officedocument.spreadsheetml.printerSettings"" Extension=""bin""/><Default ContentType=""application/xml"" Extension=""xml""/><Default ContentType=""image/jpeg"" Extension=""jpg""/><Default ContentType=""image/png"" Extension=""png""/><Default ContentType=""image/gif"" Extension=""gif""/><Default ContentType=""application/vnd.openxmlformats-package.relationships+xml"" Extension=""rels""/>");
|
||||
foreach (var p in _zipDictionary)
|
||||
sb.Append($"<Override ContentType=\"{p.Value.ContentType}\" PartName=\"/{p.Key}\" />");
|
||||
sb.Append("</Types>");
|
||||
|
@ -31,6 +31,24 @@ namespace MiniExcelLibs.Tests
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestIssue327()
|
||||
{
|
||||
var path = PathHelper.GetTempFilePath();
|
||||
var value = new[] {
|
||||
new { id = 1, file = File.ReadAllBytes(PathHelper.GetFile("images/TestIssue327.png")) },
|
||||
new { id = 2, file = File.ReadAllBytes(PathHelper.GetFile("other/TestIssue327.txt")) },
|
||||
new { id = 3, file = File.ReadAllBytes(PathHelper.GetFile("other/TestIssue327.html")) },
|
||||
};
|
||||
MiniExcel.SaveAs(path, value);
|
||||
var rows = MiniExcel.Query(path,true).ToList();
|
||||
Assert.Equal(value[0].file, rows[0].file);
|
||||
Assert.Equal(value[1].file, rows[1].file);
|
||||
Assert.Equal(value[2].file, rows[2].file);
|
||||
Assert.Equal("Hello MiniExcel", Encoding.UTF8.GetString(rows[1].file));
|
||||
Assert.Equal("<html>Hello MiniExcel</html>", Encoding.UTF8.GetString(rows[2].file));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestIssue316()
|
||||
{
|
||||
@ -343,10 +361,10 @@ namespace MiniExcelLibs.Tests
|
||||
{
|
||||
var config = new OpenXmlConfiguration() { ConvertByteArrayToBase64String = false };
|
||||
var rows = MiniExcel.Query(path, true, configuration: config).ToList();
|
||||
var expectedBase64 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAIAAAD9b0jDAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAEXRFWHRTb2Z0d2FyZQBTbmlwYXN0ZV0Xzt0AAALNSURBVEiJ7ZVLTBNBGMdndrfdIofy0ERbCgcFeYRuCy2JGOPNRA9qeIZS6YEEogQj0YMmGOqDSATxQaLRxKtRID4SgjGelUBpaQvGZ7kpII8aWtjd2dkdDxsJoS1pIh6M/k+z8833m/3+8+0OJISArRa15cT/0D8CZTYPe32+Zy+GxjzjMzOzAACDYafdZquqOG7hzJtkwUQthRC6cavv0eN+QRTBujUQQp1OV1dbffZMq1arTRaqKIok4eZTrSNjHqIo6gIIIQBgbQwpal+Z/f7dPo2GoaiNHtJut3vjPhBe7+kdfvW61Mq1nGyaX1xYjkRzsk2Z6Rm8IOTvzWs73SLwwqjHK4jCgf3lcV6VxGgiECji7AXm0gvtHYQQnue/zy8ghCRJWlxaWuV5Qsilq9cKzLYiiz04ORVLiHP6A4NPRQlhjLWsVpZlnU63Y3umRqNhGCYjPV3HsrIsMwyDsYQQejIwGEuIA/WMT1AAaDSahnoHTdPKL1vXPKVp2umoZVkWAOj1+ZOCzs7NKYTo9XqjYRcAgKIo9ZRUu9VxltGYZTQAAL5+m0kKijEmAPCrqyJCcRuOECKI4lL4ByEEYykpaE62iQIgurLi9wchhLIsry8fYwwh9PomwuEwACDbZEoKauHMgKJSU1PbOy6Hpqdpml5fPsMwn7+EOru6IYQAghKrJSloTVUFURSX02G3lRw+WulqbA4EJ9XQh4+f2s6dr65zhkLTEEIKwtqaylhCnG/fauFO1Nfde/Bw6Hm/0WiYevc+LU2vhlK2pQwNvwQAsCwrYexyOrji4lhCnOaXZRljXONoOHTk2Ju3I/5AcC3EC0JZ+cE9Bea8IqursUkUker4BsWBqpIk6aL7Sm4htzvfvByJqJORaDS3kMsvLuns6kYIJcpNCFU17pvouXlHEET1URDEnt7bo2OezbMS/vp+R3/PdfKPQ38Ccg0E/CDcpY8AAAAASUVORK5CYII=";
|
||||
var actulBase64 = (string)rows[0].Image;
|
||||
Assert.Equal(expectedBase64, actulBase64);
|
||||
var image = (string)rows[0].Image;
|
||||
Assert.StartsWith("@@@fileid@@@,xl/media/", image);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -367,7 +385,7 @@ namespace MiniExcelLibs.Tests
|
||||
MiniExcel.SaveAs(path, value);
|
||||
|
||||
{
|
||||
Assert.Contains("/xl/media/image", Helpers.GetZipFileContent(path, "xl/drawings/_rels/drawing1.xml.rels"));
|
||||
Assert.Contains("/xl/media/", Helpers.GetZipFileContent(path, "xl/drawings/_rels/drawing1.xml.rels"));
|
||||
Assert.Contains("ext cx=\"609600\" cy=\"190500\"", Helpers.GetZipFileContent(path, "xl/drawings/drawing1.xml"));
|
||||
Assert.Contains("/xl/drawings/drawing1.xml", Helpers.GetZipFileContent(path, "[Content_Types].xml"));
|
||||
Assert.Contains("drawing r:id=", Helpers.GetZipFileContent(path, "xl/worksheets/sheet1.xml"));
|
||||
|
Loading…
Reference in New Issue
Block a user