使用 Fine Uploader 分块上传文件,合并后会损坏
Uploading files in chunks with Fine Uploader, corrupt when merged back together
我正在使用具有并发分块功能的 fineuploader (https://fineuploader.com) 将文件上传到服务器。对于小文件,它工作得很好,但对于大文件,我发现合并文件最终损坏的问题。
例如,我尝试了一个 2.7GB 的 Zip 文件,最终文件的字节大小完全正确,但无法提取('File is invalid' 和 'Unconfirmed start of archive')。
我也试过一个 850MB 的 PDF,但最终损坏了,无法查看。
所有 tmp 文件都上传正常,数量与 'qqtotalparts' 的预期数量相符。我已尝试将 partSize 从 2000000 更改为更大的尺寸,但仍然遇到同样的问题。
不确定哪里出错了,但如果有任何帮助或建议,我们将不胜感激!
Javascript:
var manualUploader = new qq.FineUploader({
element: document.getElementById("fine-uploader-manual-trigger"),
template: 'qq-template-manual-trigger',
request: {
endpoint: "application.aspx?p=testnewhtml5storefiles"
},
deleteFile: {
enabled: true,
endpoint: "application.aspx?p=testnewhtml5storefiles"
},
chunking: {
enabled: true,
partSize: 10000000,
concurrent: {
enabled: true
},
success: {
endpoint: "application.aspx?p=testnewhtml5storefiles?done=1"
}
},
resume: {
enabled: true
},
retry: {
//enableAuto: true,
showButton: true
},
thumbnails: {
placeholders: {
waitingPath: 'images/waiting-generic.png',
notAvailablePath: 'images/not_available-generic.png'
}
},
autoUpload: false,
debug: true
});
服务器端:
Dim totalParts as integer = CInt(Request("qqtotalparts") )
Dim partIndex as integer = CInt(Request("qqpartindex") )
Dim filename as string = Request("qqfilename")
Dim totalFileSizeName As string = Request("qqtotalfilesize")
Dim uploadedTemp as string = "\testing\chunks\"
Dim uploadedLocation As String = "\testing\"
System.IO.Directory.CreateDirectory(uploadedTemp)
Dim filePath As String = System.IO.Path.Combine(uploadedTemp, partIndex & Convert.ToString(".tmp"))
If Not System.IO.File.Exists(filePath) Then
Dim inputStream As System.IO.Stream = request.Files(0).InputStream
Using fileStream As System.IO.FileStream = System.IO.File.OpenWrite(filePath)
inputStream.CopyTo(fileStream)
End Using
End If
'check if we have all parts
If partIndex = (totalParts - 1) Then
'merge parts into one file
mergeTempFiles(uploadedTemp, uploadedLocation, filename)
End If
Public Sub mergeTempFiles(pathOrigin As String, pathToSave As String, filename As String)
Dim tmpfiles As String() = System.IO.Directory.GetFiles(pathOrigin, "*.tmp")
If Not System.IO.Directory.Exists(pathToSave) Then
System.IO.Directory.CreateDirectory(pathToSave)
End If
Dim outPutFile As New System.IO.FileStream(pathToSave & filename, System.IO.FileMode.Create, System.IO.FileAccess.Write)
For Each tempFile As String In tmpfiles
Dim bytesRead As Integer = 0
Dim buffer As Byte() = New Byte(1023) {}
Dim inputTempFile As New System.IO.FileStream(tempFile, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Read)
While (InlineAssignHelper(bytesRead, inputTempFile.Read(buffer, 0, 1024))) > 0
outPutFile.Write(buffer, 0, bytesRead)
End While
inputTempFile.Close()
Next
outPutFile.Close()
End Sub
为了防止其他人遇到同样的问题,我找到了解决方案。
事实证明,某些文件类型(例如 PDF)的 .tmp 文件需要按照它们创建时的顺序进行合并。
所以我需要检查是否已收到所有部分,然后遍历它们并复制到我的输出文件。
例如
dim tempFile as string = ""
using outPutFile as System.IO.FileStream = File.Create(pathToSave & filename)
for x as integer = 0 to totalParts-1
tempFile = pathOrigin & x & ".tmp"
using input as System.IO.FileStream = File.OpenRead(tempFile)
input.CopyTo(outPutFile)
end using
File.Delete(tempFile)
Next
end using
我正在使用具有并发分块功能的 fineuploader (https://fineuploader.com) 将文件上传到服务器。对于小文件,它工作得很好,但对于大文件,我发现合并文件最终损坏的问题。
例如,我尝试了一个 2.7GB 的 Zip 文件,最终文件的字节大小完全正确,但无法提取('File is invalid' 和 'Unconfirmed start of archive')。
我也试过一个 850MB 的 PDF,但最终损坏了,无法查看。
所有 tmp 文件都上传正常,数量与 'qqtotalparts' 的预期数量相符。我已尝试将 partSize 从 2000000 更改为更大的尺寸,但仍然遇到同样的问题。
不确定哪里出错了,但如果有任何帮助或建议,我们将不胜感激!
Javascript:
var manualUploader = new qq.FineUploader({
element: document.getElementById("fine-uploader-manual-trigger"),
template: 'qq-template-manual-trigger',
request: {
endpoint: "application.aspx?p=testnewhtml5storefiles"
},
deleteFile: {
enabled: true,
endpoint: "application.aspx?p=testnewhtml5storefiles"
},
chunking: {
enabled: true,
partSize: 10000000,
concurrent: {
enabled: true
},
success: {
endpoint: "application.aspx?p=testnewhtml5storefiles?done=1"
}
},
resume: {
enabled: true
},
retry: {
//enableAuto: true,
showButton: true
},
thumbnails: {
placeholders: {
waitingPath: 'images/waiting-generic.png',
notAvailablePath: 'images/not_available-generic.png'
}
},
autoUpload: false,
debug: true
});
服务器端:
Dim totalParts as integer = CInt(Request("qqtotalparts") )
Dim partIndex as integer = CInt(Request("qqpartindex") )
Dim filename as string = Request("qqfilename")
Dim totalFileSizeName As string = Request("qqtotalfilesize")
Dim uploadedTemp as string = "\testing\chunks\"
Dim uploadedLocation As String = "\testing\"
System.IO.Directory.CreateDirectory(uploadedTemp)
Dim filePath As String = System.IO.Path.Combine(uploadedTemp, partIndex & Convert.ToString(".tmp"))
If Not System.IO.File.Exists(filePath) Then
Dim inputStream As System.IO.Stream = request.Files(0).InputStream
Using fileStream As System.IO.FileStream = System.IO.File.OpenWrite(filePath)
inputStream.CopyTo(fileStream)
End Using
End If
'check if we have all parts
If partIndex = (totalParts - 1) Then
'merge parts into one file
mergeTempFiles(uploadedTemp, uploadedLocation, filename)
End If
Public Sub mergeTempFiles(pathOrigin As String, pathToSave As String, filename As String)
Dim tmpfiles As String() = System.IO.Directory.GetFiles(pathOrigin, "*.tmp")
If Not System.IO.Directory.Exists(pathToSave) Then
System.IO.Directory.CreateDirectory(pathToSave)
End If
Dim outPutFile As New System.IO.FileStream(pathToSave & filename, System.IO.FileMode.Create, System.IO.FileAccess.Write)
For Each tempFile As String In tmpfiles
Dim bytesRead As Integer = 0
Dim buffer As Byte() = New Byte(1023) {}
Dim inputTempFile As New System.IO.FileStream(tempFile, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Read)
While (InlineAssignHelper(bytesRead, inputTempFile.Read(buffer, 0, 1024))) > 0
outPutFile.Write(buffer, 0, bytesRead)
End While
inputTempFile.Close()
Next
outPutFile.Close()
End Sub
为了防止其他人遇到同样的问题,我找到了解决方案。
事实证明,某些文件类型(例如 PDF)的 .tmp 文件需要按照它们创建时的顺序进行合并。
所以我需要检查是否已收到所有部分,然后遍历它们并复制到我的输出文件。
例如
dim tempFile as string = ""
using outPutFile as System.IO.FileStream = File.Create(pathToSave & filename)
for x as integer = 0 to totalParts-1
tempFile = pathOrigin & x & ".tmp"
using input as System.IO.FileStream = File.OpenRead(tempFile)
input.CopyTo(outPutFile)
end using
File.Delete(tempFile)
Next
end using