我试图通过Ajax将文件上传到用经典ASP编写的服务器端脚本。
这是相关的HTML和JavaScript代码:
<input type="file" id="fileInput" />
和
function saveToServer(file) {
const fd = new FormData();
fd.append('image', file);
const xhr = new XMLHttpRequest();
xhr.open('POST', 'http://localhost/post.asp', true);
xhr.onload = () => {
if (xhr.status === 200) {
// Do stuff with response
}
};
xhr.send(fd);
}
const fileInput = document.getElementById("fileInput");
fileInput.addEventListener("change", () => {
const file = fileInput.files[0];
if (/^image\//.test(file.type)) {
saveToServer(file);
} else {
console.warn('You can only upload images.');
}
});
我的问题是:如何在我的经典ASP页面(post.asp)中获取对上传文件的引用?
在PHP中有一个全局变量$ _FILES可用,它包含类似于:
Array
(
[image] => Array
(
[name] => cat.png
[type] => image/png
[tmp_name] => /tmp/phpOjXMW3
[error] => 0
[size] => 10603
)
)
Classic ASP中有相同的东西吗?
这是帖子页面:
Set upl = New FileUploader
upl.Upload()
If upl.Files.Count = 1 Then
For Each File In upl.Files.Items
If File.FileSize < 100000 Then
File.FileName = upl.Form ("id") & ".jpg"
File.SaveToDisk Server.MapPath("/Images")
next
end if
这是帖子页面顶部的一个包含:
Class FileUploader
Public Files
Private mcolFormElem
Private Sub Class_Initialize()
Set Files = Server.CreateObject("Scripting.Dictionary")
Set mcolFormElem = Server.CreateObject("Scripting.Dictionary")
End Sub
Private Sub Class_Terminate()
If IsObject(Files) Then
Files.RemoveAll()
Set Files = Nothing
End If
If IsObject(mcolFormElem) Then
mcolFormElem.RemoveAll()
Set mcolFormElem = Nothing
End If
End Sub
Public Property Get Form(sIndex)
Form = ""
If mcolFormElem.Exists(LCase(sIndex)) Then Form = mcolFormElem.Item(LCase(sIndex))
End Property
Public Default Sub Upload()
Dim biData, sInputName
Dim nPosBegin, nPosEnd, nPos, vDataBounds, nDataBoundPos
Dim nPosFile, nPosBound
'response.Flush
biData = Request.BinaryRead(Request.TotalBytes)
nPosBegin = 1
nPosEnd = InstrB(nPosBegin, biData, CByteString(Chr(13)))
If (nPosEnd-nPosBegin) <= 0 Then Exit Sub
vDataBounds = MidB(biData, nPosBegin, nPosEnd-nPosBegin)
nDataBoundPos = InstrB(1, biData, vDataBounds)
Do Until nDataBoundPos = InstrB(biData, vDataBounds & CByteString("--"))
nPos = InstrB(nDataBoundPos, biData, CByteString("Content-Disposition"))
nPos = InstrB(nPos, biData, CByteString("name="))
nPosBegin = nPos + 6
nPosEnd = InstrB(nPosBegin, biData, CByteString(Chr(34)))
sInputName = CWideString(MidB(biData, nPosBegin, nPosEnd-nPosBegin))
nPosFile = InstrB(nDataBoundPos, biData, CByteString("filename="))
nPosBound = InstrB(nPosEnd, biData, vDataBounds)
If nPosFile <> 0 And nPosFile < nPosBound Then
Dim oUploadFile, sFileName
Set oUploadFile = New UploadedFile
oUploadFile.FormElement = MidB(biData, nPos, 5)
nPosBegin = nPosFile + 10
nPosEnd = InstrB(nPosBegin, biData, CByteString(Chr(34)))
sFileName = CWideString(MidB(biData, nPosBegin, nPosEnd-nPosBegin))
oUploadFile.FileName = Right(sFileName, Len(sFileName)-InStrRev(sFileName, "\"))
nPos = InstrB(nPosEnd, biData, CByteString("Content-Type:"))
nPosBegin = nPos + 14
nPosEnd = InstrB(nPosBegin, biData, CByteString(Chr(13)))
oUploadFile.ContentType = CWideString(MidB(biData, nPosBegin, nPosEnd-nPosBegin))
nPosBegin = nPosEnd+4
nPosEnd = InstrB(nPosBegin, biData, vDataBounds) - 2
oUploadFile.FileData = MidB(biData, nPosBegin, nPosEnd-nPosBegin)
If oUploadFile.FileSize > 0 Then Files.Add LCase(sInputName), oUploadFile
Else
nPos = InstrB(nPos, biData, CByteString(Chr(13)))
nPosBegin = nPos + 4
nPosEnd = InstrB(nPosBegin, biData, vDataBounds) - 2
If Not mcolFormElem.Exists(LCase(sInputName)) Then mcolFormElem.Add LCase(sInputName), CWideString(MidB(biData, nPosBegin, nPosEnd-nPosBegin))
End If
nDataBoundPos = InstrB(nDataBoundPos + LenB(vDataBounds), biData, vDataBounds)
Loop
End Sub
'String to byte string conversion
Private Function CByteString(sString)
Dim nIndex
For nIndex = 1 to Len(sString)
CByteString = CByteString & ChrB(AscB(Mid(sString,nIndex,1)))
Next
End Function
'Byte string to string conversion
Private Function CWideString(bsString)
Dim nIndex
CWideString =""
For nIndex = 1 to LenB(bsString)
CWideString = CWideString & Chr(AscB(MidB(bsString,nIndex,1)))
Next
End Function
End Class
Class UploadedFile
Public ContentType
Public FileName
Public FileData
Public FormElement
Public Property Get FileSize()
FileSize = LenB(FileData)
End Property
Public Sub SaveToDisk(sPath)
Dim oFS, oFile
Dim nIndex
If sPath = "" Or FileName = "" Then Exit Sub
If Mid(sPath, Len(sPath)) <> "\" Then sPath = sPath & "\"
Set oFS = Server.CreateObject("Scripting.FileSystemObject")
If Not oFS.FolderExists(sPath) Then Exit Sub
Set oFile = oFS.CreateTextFile(sPath & FileName, True)
For nIndex = 1 to LenB(FileData)
oFile.Write Chr(AscB(MidB(FileData,nIndex,1)))
Next
oFile.Close
End Sub
Public Sub SaveToDatabase(ByRef oField)
If LenB(FileData) = 0 Then Exit Sub
If IsObject(oField) Then
oField.AppendChunk FileData
End If
End Sub
End Class
上传文件后,您可以使用FileSystemObject
检查文件是否存在,并通过GetFile
方法检索其属性。使用函数来节省空间并返回属性字典,使它们更容易引用:
function getFileInfo(ByVal fileLocation)
' Use MapPath to convert to an absolute path
fileLocation = Server.MapPath(fileLocation)
' Set the file system and dictionary objects using reserved words
set fileSystem = Server.CreateObject("Scripting.FileSystemObject")
Set dictionary = Server.CreateObject("Scripting.Dictionary")
' Check that the file exists
if fileSystem.FileExists(fileLocation) then
' Use GetFile to retrieve the files properties
set file = fileSystem.GetFile(fileLocation)
' Add each property to the dictionary object
dictionary.add "FileFound",true
dictionary.add "Attributes",file.Attributes
dictionary.add "DateCreated",file.DateCreated
dictionary.add "DateLastAccessed",file.DateLastAccessed
dictionary.add "DateLastModified",file.DateLastModified
dictionary.add "Drive",file.Drive
dictionary.add "Name",file.Name
dictionary.add "ParentFolder",file.ParentFolder
dictionary.add "Path",file.Path
dictionary.add "ShortName",file.ShortName
dictionary.add "ShortPath",file.ShortPath
dictionary.add "Size",file.Size
dictionary.add "Type",file.Type
' Attributes translations:
' 0 = Normal file
' 1 = Read-only file
' 2 = Hidden file
' 4 = System file
' 16 = Folder or directory
' 32 = File has changed since last backup
' 1024 = Link or shortcut
' 2048 = Compressed file
else
' File not found
dictionary.add "FileFound",false
end if
' Return the dictionary object
set getFileInfo = dictionary
' Set all objects to nothing
set fileSystem = nothing
set dictionary = nothing
set file = nothing
end function
要检查文件是否已上载并检索其属性:
Dim fileInfo : Set fileInfo = getFileInfo("../../uploads/cat.jpg")
' getFileInfo("/Images/" & upl.Form ("id") & ".jpg")
if fileInfo.item("FileFound") then
' Output all the file properties
for each item in fileInfo
response.write "<b>" & item & "</b>: " & fileInfo.item(item) & "<br>"
next
' Output a specific file property
response.write "<b>The file size is</b>: " & fileInfo.item("Size") & " bytes<br>"
response.write "<b>The file type is</b>: " & fileInfo.item("Type") & "<br>"
else
response.write "File not found"
end if
Set fileInfo = nothing
示例输出:
FileFound:是的 属性:32 DateCreated:20/03/2019 12:40:09 DateLastAccessed:20/03/2019 12:40:09 DateLastModified:20/03/2019 12:40:09 开车:C: 姓名:cat.jpg ParentFolder:C:\ inetpub \ wwwroot \ uploads 路径:C:\ inetpub \ wwwroot \ uploads \ cat.jpg ShortName:cat.jpg ShortPath:C:\ inetpub \ wwwroot \ uploads \ cat.jpg 大小:992514 类型:JPEG图像 文件大小为:992514字节 文件类型为:JPEG图像
编辑:继Lankymart的评论后,您可以使用upl.Files
对象执行一些初步检查,然后将文件保存到磁盘:
function randomFileName()
' Randomize() generates quite a small seed number, so you will generate duplicate
' filenames if you upload enough images. To prevent this, prefix a random number
' with a unix timestamp.
Dim uts : uts = DateDiff("s","1970-01-01 00:00:00",Now())
Randomize()
' filename format: [unix timestamp][random 7 digit number]
randomFileName = cStr(uts & Int((9999999-1000000+1)*Rnd+1000000))
end function
function validExtension(ByVal allowed, ByVal fileName)
Dim extRegexp : Set extRegexp = New RegExp
extRegexp.Pattern = "^.*\.(" & lCase(allowed) & ")$"
validExtension = extRegexp.Test(lCase(fileName))
end function
if Request.TotalBytes > 0 then
Const max_upload_size = 100000 ' bytes
Const allowed_extensions = "jpg|jpeg|png"
Const upload_folder = "/Images/"
Dim upload_successful : upload_successful = false
Dim upload_message : upload_message = ""
Dim rndFileName, fileExt, fileSplit
Dim upl : Set upl = New FileUploader
upl.Upload()
If upl.Files.Count = 1 Then
For Each File In upl.Files.Items
file.ContentType = lCase(file.ContentType)
File.FileName = trim(File.FileName)
if NOT (file.ContentType = "image/jpeg" _
OR file.ContentType = "image/jpg" _
OR file.ContentType = "image/png") then
upload_message = "Invalid file type"
elseif NOT validExtension(allowed_extensions,File.FileName) then
upload_message = "Invalid file type"
elseif File.FileSize > max_upload_size then
upload_message = "File too big"
else
' Extract the file extension
fileSplit = split(File.FileName,".")
fileExt = lCase(fileSplit(uBound(fileSplit)))
' Generate a random file name
rndFileName = randomFileName() & "." & fileExt
' Everything checks out, save to disk
File.FileName = rndFileName
File.SaveToDisk Server.MapPath(upload_folder)
upload_message = "Upload successful"
upload_successful = true
end if
next
else
upload_message = "Maximum upload count exceeded"
end if
Set upl = nothing
' Return a JSON string
Response.ContentType = "application/json"
response.write _
"{""uploaded"":" & lCase(upload_successful) & "," &_
"""message"":""" & upload_message & """," &_
"""file"":""" & upload_folder & rndFileName & """}"
end if
这个问题没有多大意义......
我的问题是:
如何在Classic ASP页面(post.asp)中获取对上传文件的引用?
从您发布的代码中可以清楚地看到,您正在使用自定义类来支持上传FileUploader
,它会为您解析二进制文件并构建一组表示上传文件的对象(UploadedFile
类)。
在您发布的代码中,您正在访问UploadedFile
循环中的For Each
对象;
Set upl = New FileUploader
upl.Upload()
If upl.Files.Count = 1 Then
For Each File In upl.Files.Items
If File.FileSize < 100000 Then
File.FileName = upl.Form ("id") & ".jpg"
File.SaveToDisk Server.MapPath("/Images")
End If
Next
End If
修正了在End If
结束之前For Each
失踪的错字。
在该示例中,您的File
对象是UploadedFile
类对象,其中包含FileUploader
在二进制解析期间填充的文件属性。